
#ifndef __LINMIN_H__

#include <gsl/gsl_multimin.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef struct
{
  gsl_multimin_function_fdf *fdf;
  gsl_vector *x;
  gsl_vector *g;
  gsl_vector *d;
  double eta;
}
lineminimizer_setup;

typedef struct
{
  const char *name;
  size_t size;
  int (*alloc) (void *state, size_t n);
  int (*minimize) (void *state,
                   const lineminimizer_setup *setup,
                   double alpha0,
                   double f,
                   double *alpha,
                   gsl_vector *x_plus,
                   double *f_plus,
                   gsl_vector *g_plus);
  void (*free) (void *state);
}
lineminimizer_type;

typedef struct
{
  const lineminimizer_type *type;
  const lineminimizer_setup *setup;
  void *state;
}
lineminimizer;

lineminimizer *
lineminimizer_alloc (const lineminimizer_type *T,
                     size_t n);

inline double 
lineminimizer_initstep_fletcher (double dphi0,
                                 double delta_f);

int 
lineminimizer_minimize (lineminimizer *lm,
                        gsl_multimin_function_fdf *fdf,
                        double alpha0,
                        double eta,
                        double f,
                        gsl_vector *x,
                        gsl_vector *g,
                        gsl_vector *d,
                        double *alpha,
                        gsl_vector *x_plus,
                        double *f_plus,
                        gsl_vector *g_plus);

void 
lineminimizer_free (lineminimizer *lm);

extern const lineminimizer_type *lineminimizer_fletcher;
extern const lineminimizer_type *lineminimizer_morethuente;

/* This function sets the gamma parameter for the 
 * sufficient descent condition. */
void 
lineminimizer_morethuente_set_gamma (lineminimizer *lm,
                                     double gamma);

#ifdef __cplusplus
}
#endif

#define __LINMIN_H__

#endif
